package com.vftour.stu.mq.rabbitmq.config;

import com.vftour.stu.mq.rabbitmq.constant.RabbitConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * RabbitMqConfiguration
 *
 * @version 1.0
 * @author: 东东 | d@tke.store
 * @date :  2022/3/5 3:06 下午
 */
@Slf4j
@Configuration
public class RabbitMqConfiguration {

    @Bean
    public RabbitTemplate rabbitTemplate(CachingConnectionFactory connectionFactory) {
        connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
        connectionFactory.setPublisherReturns(true);
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> log.info("消息发送成功:correlationData({}),ack({}),cause({})", correlationData, ack, cause));
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}", exchange, routingKey, replyCode, replyText, message));
        return rabbitTemplate;
    }

    /**
     * 使用json序列化消息，接收和发送都需要
     * @return
     */
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public MessageConverter messageRecoverer() {
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 直接模式队列1
     */
    @Bean
    public Queue directQueue() {
        return new Queue(RabbitConstant.QUEUE_SIMPLE);
    }

    /**
     * 分列模式队列 声明交换机
     */
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(RabbitConstant.FANOUT_MODE_QUEUE);
    }

    /**
     * 队列
     */
    @Bean
    public Queue fanoutQueueOne() {
        return new Queue(RabbitConstant.FANOUT_QUEUE_ONE);
    }

    /**
     * 队列
     */
    @Bean
    public Queue fanoutQueueTwo() {
        return new Queue(RabbitConstant.FANOUT_QUEUE_TWO);
    }

    /**
     * 分列模式绑定队列1和交换机
     *
     * @param fanoutQueueOne 绑定队列1
     * @param fanoutExchange 分列模式交换器
     */
    @Bean
    public Binding fanoutBindingOne(Queue fanoutQueueOne, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(fanoutQueueOne).to(fanoutExchange);
    }

    /**
     * 分列模式绑定队列2和交换机
     *
     * @param fanoutQueueTwo 绑定队列1
     * @param fanoutExchange 分列模式交换器
     */
    @Bean
    public Binding fanoutBindingTwo(Queue fanoutQueueTwo, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(fanoutQueueTwo).to(fanoutExchange);
    }
}
